﻿module Preprocessor.PrintUtils

open Cabs
open Clexer
open Lexer
open System.Text

let TokenToString token = 
    match token with
        | IDENT(x, _) -> x
        | QUALIFIER(x, _) -> x
        | CST_CHAR(x, _) -> x.ToString()
        | CST_WCHAR(x, _) -> x.ToString()
        | CST_INT(x, _) -> x
        | CST_FLOAT(x, _) -> x
        | NAMED_TYPE(x, _) -> x
        | CST_STRING(x, _) -> x.ToString()
        | CST_WSTRING(x, _) -> x.ToString()
        | EOF(_) -> ""
        | CHAR(_) -> "char"
        | INT(_) -> "int"
        | BOOL(_) -> "bool"
        | DOUBLE(_) -> "double"
        | FLOAT(_) -> "float"
        | VOID(_) -> "void"
        | INT64(_) -> "int64"
        | INT32(_) -> "int32"
        | ENUM(_) -> "enum"
        | STRUCT(_) -> "struct"
        | TYPEDEF(_) -> "typedef"
        | UNION(_) -> "union"
        | SIGNED(_) -> "signed"
        | UNSIGNED(_) -> "unsigned"
        | LONG(_) -> "long"
        | SHORT(_) -> "short"
        | VOLATILE(_) -> "volatile"
        | EXTERN(_) -> "extern"
        | STATIC(_) -> "static"
        | CONST(_) -> "const"
        | RESTRICT(_) -> "restict"
        | AUTO(_) -> "auto"
        | REGISTER(_) -> "register"
        | THREAD(_) -> "thread"
        | SIZEOF(_) -> "sizeof"
        | ALIGNOF(_) -> "alignof"
        | EQ(_) -> "="
        | PLUS_EQ(_) -> "+="
        | MINUS_EQ(_) -> "-="
        | STAR_EQ(_) -> "*="
        | SLASH_EQ(_) -> "/="
        | PERCENT_EQ(_) -> "%="
        | AND_EQ(_) -> "&="
        | PIPE_EQ(_) -> "|="
        | CIRC_EQ(_) -> "^="
        | INF_INF_EQ(_) -> "<<="
        | SUP_SUP_EQ(_) -> ">>="
        | ARROW(_) -> "->"
        | DOT(_) -> "."
        | EQ_EQ(_) -> "=="
        | EXCLAM_EQ(_) -> "!="
        | INF(_) -> "<"
        | SUP(_) -> ">"
        | INF_EQ(_) -> "<="
        | SUP_EQ(_) -> ">="
        | PLUS(_) -> "+"
        | MINUS(_) -> "-"
        | STAR(_) -> "*"
        | SLASH(_) -> "/"
        | PERCENT(_) -> "%"
        | TILDE(_) -> "~"
        | AND(_) -> "&"
        | PIPE(_) -> "|"
        | CIRC(_) -> "^"
        | EXCLAM(_) -> "!"
        | AND_AND(_) -> "&&"
        | PIPE_PIPE(_) -> "||"
        | INF_INF(_) -> ">>"
        | SUP_SUP(_) -> "<<"
        | PLUS_PLUS(_) -> "++"
        | MINUS_MINUS(_) -> "--"
        | RPAREN(_) -> ")"
        | LPAREN(_) -> "(" 
        | RBRACE(_) -> "}"
        | LBRACE(_) -> "{"
        | LBRACKET(_) -> "["
        | RBRACKET(_) -> "]"
        | COLON(_) -> ":"
        | SEMICOLON(_) -> ";"
        | COMMA(_) -> ","
        | ELLIPSIS(_) -> "..."
        | QUEST(_) -> "?"
        | BREAK(_) -> "break"
        | CONTINUE(_) -> "continue"
        | GOTO(_) -> "goto"
        | RETURN(_) -> "return"
        | SWITCH(_) -> "switch"
        | CASE(_) -> "case"
        | DEFAULT(_) -> "default"
        | WHILE(_) -> "while"
        | DO(_) -> "do"
        | FOR(_) -> "for"
        | IF(_) -> "if"
        | TRY(_) -> "try"
        | EXCEPT(_) -> "except"
        | FINALLY(_) -> "finally"
        | ELSE(_) -> "else"
        | ATTRIBUTE(_) -> "attribute"
        | INLINE(_) -> "inline"
        | ASM(_) -> "asm"
        | TYPEOF(_) -> "typeof"
        | FUNCTION__(_) -> ""
        | PRETTY_FUNCTION__(_) -> ""
        | LABEL__(_) -> ""
        | BUILTIN_VA_ARG(_) -> ""
        | ATTRIBUTE_USED(_) -> ""
        | BUILTIN_VA_LIST(_) -> ""
        | BLOCKATTRIBUTE(_) -> ""
        | BUILTIN_TYPES_COMPAT(_) -> ""
        | BUILTIN_OFFSETOF(_) -> ""
        | DECLSPEC(_) -> ""
        | MSASM(x, _) -> ""
        | MSATTR(x, _) -> ""
        | PRAGMA_LINE(_) -> ""
        | PRAGMA(_) -> ""
        | PRAGMA_EOL(_) -> ""
        | AT_TRANSFORM(_) -> ""
        | AT_TRANSFORMEXPR(_) -> ""
        | AT_SPECIFIER(_) -> ""
        | AT_EXPR(_) -> ""
        | AT_NAME(_) -> ""
        | DIRECTIVE_DEFINE(_) -> "#define"
        | DIRECTIVE_INCLUDE(x, _) -> ("#include " + x)
        | DIRECTIVE_INCLUDENEXT(x,_) -> ("#include_next " + x)
        | DIRECTIVE_IF(x) -> "#if"
        | DIRECTIVE_ELSE(_) -> "#else"
        | DIRECTIVE_IFDEF(x, _) -> "#ifdef" + x
        | DIRECTIVE_IFNDEF(x, _) -> "#ifndef" + x
        | DIRECTIVE_ELIF(_) -> "#elif"
        | DIRECTIVE_ENDIF(_) -> "#endif"
        | DIRECTIVE_UNDEF(x, _) -> ("#undef " + x)
        | DIRECTIVE_EOL(_) -> ""
        | DIRECTIVE_CONCAT(_) -> "##" 
        | COMMENT(x, _) -> "/*" + x + "*/"
        | COMMENT_ONELINE(x, _) -> "//" + x

let GetLoc token = 
    match token with
        | IDENT(_, x) -> x
        | QUALIFIER(_, x) -> x
        | CST_CHAR(_, x) -> x
        | CST_WCHAR(_, x) -> x
        | CST_INT(_, x) -> x
        | CST_FLOAT(_, x) -> x
        | NAMED_TYPE(_, x) -> x
        | CST_STRING(_, x) -> x
        | CST_WSTRING(_, x) -> x
        | EOF(x) -> x
        | CHAR(x) -> x
        | INT(x) -> x
        | BOOL(x) -> x
        | DOUBLE(x) -> x
        | FLOAT(x) -> x
        | VOID(x) -> x
        | INT64(x) -> x
        | INT32(x) -> x
        | ENUM(x) -> x
        | STRUCT(x) -> x
        | TYPEDEF(x) -> x
        | UNION(x) -> x
        | SIGNED(x) -> x
        | UNSIGNED(x) -> x
        | LONG(x) -> x
        | SHORT(x) -> x
        | VOLATILE(x) -> x
        | EXTERN(x) -> x
        | STATIC(x) -> x
        | CONST(x) -> x
        | RESTRICT(x) -> x
        | AUTO(x) -> x
        | REGISTER(x) -> x
        | THREAD(x) -> x
        | SIZEOF(x) -> x
        | ALIGNOF(x) -> x
        | EQ(x) -> x
        | PLUS_EQ(x) -> x
        | MINUS_EQ(x) -> x
        | STAR_EQ(x) -> x
        | SLASH_EQ(x) -> x
        | PERCENT_EQ(x) -> x
        | AND_EQ(x) -> x
        | PIPE_EQ(x) -> x
        | CIRC_EQ(x) -> x
        | INF_INF_EQ(x) -> x
        | SUP_SUP_EQ(x) -> x
        | ARROW(x) -> x
        | DOT(x) -> x
        | EQ_EQ(x) -> x
        | EXCLAM_EQ(x) -> x
        | INF(x) -> x
        | SUP(x) -> x
        | INF_EQ(x) -> x
        | SUP_EQ(x) -> x
        | PLUS(x) -> x
        | MINUS(x) -> x
        | STAR(x) -> x
        | SLASH(x) -> x
        | PERCENT(x) -> x
        | TILDE(x) -> x
        | AND(x) -> x
        | PIPE(x) -> x
        | CIRC(x) -> x
        | EXCLAM(x) -> x
        | AND_AND(x) -> x
        | PIPE_PIPE(x) -> x
        | INF_INF(x) -> x
        | SUP_SUP(x) -> x
        | PLUS_PLUS(x) -> x
        | MINUS_MINUS(x) -> x
        | RPAREN(x) -> x
        | LPAREN(x) -> x
        | RBRACE(x) -> x
        | LBRACE(x) -> x
        | LBRACKET(x) -> x
        | RBRACKET(x) -> x
        | COLON(x) -> x
        | SEMICOLON(x) -> x
        | COMMA(x) -> x
        | ELLIPSIS(x) -> x
        | QUEST(x) -> x
        | BREAK(x) -> x
        | CONTINUE(x) -> x
        | GOTO(x) -> x
        | RETURN(x) -> x
        | SWITCH(x) -> x
        | CASE(x) -> x
        | DEFAULT(x) -> x
        | WHILE(x) -> x
        | DO(x) -> x
        | FOR(x) -> x
        | IF(x) -> x
        | TRY(x) -> x
        | EXCEPT(x) -> x
        | FINALLY(x) -> x
        | ELSE(x) -> x
        | ATTRIBUTE(x) -> x
        | INLINE(x) -> x
        | ASM(x) -> x
        | TYPEOF(x) -> x
        | FUNCTION__(x) -> x
        | PRETTY_FUNCTION__(x) -> x
        | LABEL__(x) -> x
        | BUILTIN_VA_ARG(x) -> x
        | ATTRIBUTE_USED(x) -> x
        | BUILTIN_VA_LIST(x) -> x
        | BLOCKATTRIBUTE(x) -> x
        | BUILTIN_TYPES_COMPAT(x) -> x
        | BUILTIN_OFFSETOF(x) -> x
        | DECLSPEC(x) -> x
        | MSASM(_, x) -> x
        | MSATTR(_, x) -> x
        | PRAGMA_LINE(_,x) -> x
        | PRAGMA(x) -> x
        | PRAGMA_EOL(x) -> x
        | AT_TRANSFORM(x) -> x
        | AT_TRANSFORMEXPR(x) -> x
        | AT_SPECIFIER(x) -> x
        | AT_EXPR(x) -> x
        | AT_NAME(x) -> x
        | DIRECTIVE_DEFINE(x) -> x
        | DIRECTIVE_INCLUDE(_, x) -> x
        | DIRECTIVE_INCLUDENEXT(_, x) -> x
        | DIRECTIVE_IF(x) -> x
        | DIRECTIVE_ELSE(x) -> x
        | DIRECTIVE_IFDEF(_, x) -> x
        | DIRECTIVE_IFNDEF(_, x) -> x
        | DIRECTIVE_ELIF(x) -> x
        | DIRECTIVE_ENDIF(x) -> x
        | DIRECTIVE_UNDEF(_, x) -> x
        | DIRECTIVE_EOL(x) -> x
        | DIRECTIVE_CONCAT(x) -> x
        | COMMENT(_, x) -> x
        | COMMENT_ONELINE(_, x) -> x


let TokenListToString lst =
    List.fold (fun acc x -> acc + (TokenToString x) + " ") "" lst

let StringListToStringWithSeparator lst (separator:string) =
    match lst with
        | [] -> ""
        | _ -> 
            let s = new StringBuilder("("); 
            (List.fold (fun (acc:StringBuilder) (x:string) -> acc.Append(x).Append(separator).Append(' ')) s lst).Remove(s.Length - 2, 2).Append(')').ToString()